inherit CometDimitri_CFC CommonFC
package require tdom

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC constructor {} {
 set this(L_connexions)      [list]
 set this(L_instance_compo)  [list]
 set this(L_class_compo)     [list]
 set this(class_selected)    {}
 
 set this(L_possible_compo_to_enable) [list]
 
 set this(state_play_pause)  0
 
 set this(nb_compo_OK)       0
 set this(nb_compo_to_be_OK) 0
 
 set this(LC) ""
 
 set this(comet_root_to_be_transformed) ""
}

#___________________________________________________________________________________________________________________________________________
Generate_accessors CometDimitri_CFC [list state_play_pause class_selected comet_root_to_be_transformed LC]
Generate_List_accessor CometDimitri_CFC L_connexions     L_connexions
Generate_List_accessor CometDimitri_CFC L_instance_compo L_instance_compo
Generate_List_accessor CometDimitri_CFC L_class_compo    L_class_compo

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC PlayPause  {} {
 set this(state_play_pause) [expr 1 - $this(state_play_pause)]
 if {($this(nb_compo_to_be_OK) > 0) && ($this(nb_compo_to_be_OK) == $this(nb_compo_OK)) && $this(state_play_pause)} {
   after 10 "$this(LC) Step"
  }
}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Reset {} {
 set this(L_possible_compo_to_enable) [list]
 foreach compo $this(L_instance_compo) {
   # Empty inputs and outputs and reset
   $compo Reset
  }
}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Init_nb_compo_OK {} {set this(nb_compo_OK) 0}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Incr_nb_compo_OK {} {
 incr this(nb_compo_OK)
 if {($this(nb_compo_to_be_OK) == $this(nb_compo_OK)) && $this(state_play_pause)} {
   puts "Go : this(nb_compo_to_be_OK) = $this(nb_compo_to_be_OK), this(nb_compo_OK) = $this(nb_compo_OK), this(state_play_pause) = $this(state_play_pause)"
   after 10 "$this(LC) Step"
  }
}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Step  {} { 
 this Init_nb_compo_OK
 set L_compo_processable [this Enable_compo_processable]
 set this(nb_compo_to_be_OK) [llength $L_compo_processable]
 foreach compo $L_compo_processable {
   $compo set_has_processed 0
   $compo Add_style_class [list PROCESSING]
   $compo Process
   if {[$compo get_has_processed]} {
     this Propagate_outputs $compo
	 this Incr_nb_compo_OK
	} else {$compo Subscribe_to_set_has_processed $objName "if {\$v} {$objName Propagate_outputs $compo; $objName Incr_nb_compo_OK}" UNIQUE
	        puts "$compo Subscribe_to_has_processed ..."
	       }
  }
}

#___________________________________________________________________________________________________________________________________________
proc P_L_methodes_get_CometDimitri {} {return [list {get_comet_root_to_be_transformed { }} {Save_network_in_file {f_name}} {get_state_play_pause {}} {get_class_selected { }} {get_L_connexions { }} {get_L_instance_compo { }} {get_L_class_compo { }} ]}
proc P_L_methodes_set_CometDimitri {} {return [list {set_comet_root_to_be_transformed {v}} {Step {}} {PlayPause {}} {Reset {}} {set_class_selected {v}} {set_L_connexions {v}} {Add_L_connexions {v}} {Sub_L_connexions {v}} {set_L_instance_compo {v}} {Add_L_instance_compo {v}} {Sub_L_instance_compo {v}} {set_L_class_compo {v}} {Add_L_class_compo {v}} {Sub_L_class_compo {v}} ]}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Enable_compo_processable {} {
 set L_rep [list]
 foreach compo [this get_L_instance_compo] {
   # If inputs are full and consistent, then set the compo to processable
   if {[this Enable_compo $compo]} {lappend L_rep $compo}
  }
 return $L_rep
}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Enable_compo {compo} {
 set v 1; set nb_total 0; set check_for_existence 1
 foreach input [$compo get_L_inputs] {
   lassign $input input_name cardN card
   set length [llength [$compo get_Input_data $input_name]]
   incr nb_total $length
   if {$cardN != "*"} {
	 if {![info exists $cardN]} {set $cardN $length}
	 #DEBUG TO ALLOW EMPTY TRANSITION   if {[set $cardN] != $length || $length == 0} {set v 0; break}
	 if {[set $cardN] != $length || [lsearch $this(L_possible_compo_to_enable) $compo] == -1} {set v 0; break}
	 set check_for_existence 0
    }
  }
 if {[$compo get_nb_max_process] != "*"} {
   if {[$compo get_nb_process] >= [$compo get_nb_max_process]} {set v 0}
  }
 if {[llength [$compo get_L_inputs]] > 0 && $check_for_existence && $nb_total == 0} {set v 0}

 $compo Sub_style_class [list PROCESSING]
 $compo set_can_process $v

 return $v
}

#___________________________________________________________________________________________________________________________________________
method CometDimitri_CFC Propagate_outputs {compo} {
 Sub_list this(L_possible_compo_to_enable) $compo
 
 foreach connexion $this(L_connexions) {
   lassign $connexion out in
   lassign $out C_out port_out
   #OLD lassign $in  C_in  port_in
   if {$compo == $C_out} {
     #puts "  Propagate output $port_out of $compo to input $port_in of $C_in"
     #OLD $C_in set_Input_data $port_in [$compo get_Output_data $port_out]
	 if {[info exists T($port_out)]} {lappend T($port_out) $in} else {set T($port_out) [list $in]}
    }
  }
  
  
 foreach {port_out L_in} [array get T] {
   set in [lindex $L_in 0]
   lassign $in C_in port_in
   set data_out [$compo get_Output_data $port_out]
   $C_in set_Input_data $port_in $data_out
   
   Add_list this(L_possible_compo_to_enable) $C_in
   
   foreach in [lrange $L_in 1 end] {
     # Copy the individuals
	 set new_data_out [list]
	 foreach i $data_out {set new_individu [INDIVIDU [CPool get_a_unique_name] "" ""]
	                      $new_individu = $i
						  [MAGELLAN_GET_DYNASTY] add_individu $new_individu [list copy $i]
						  lappend new_data_out $new_individu
						 }
	 # Transmit the copy
	 lassign $in C_in port_in
	 $C_in set_Input_data $port_in $new_data_out
	 
	 # Save the target component as possibly to enable
	 Add_list this(L_possible_compo_to_enable) $C_in
    }
  }
 
 set L_out [$compo get_L_outputs]
 foreach out $L_out {
   $compo set_Output_data [lindex $out 0] ""
  }
}

